package edu.ccut.saturn.component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import edu.ccut.saturn.component.impl.SaturnBundleFilterInfo;
import edu.ccut.saturn.component.impl.SaturnFilterInfo;
import edu.ccut.saturn.component.utils.LoaderUtils;

/**
 * @author xiyue1314
 *
 */
public class FilterManager {

	private static FilterManager instance = new FilterManager();
	
	private Map<String,SaturnBundleFilterInfo> filterInfoMap ;
	
	
	public FilterManager() {
		this.filterInfoMap = new HashMap<String,SaturnBundleFilterInfo>();
	}

	public static FilterManager getInstance() {
		return instance;
	}
	
	public void addBundleFilterManager(IBundleInfo bundleInfo) {
		String key = bundleInfo.getBundleSymbolicName();
		SaturnBundleFilterInfo saturnBundleFilterInfo = bundleInfo.getBundleFilterInfo();
		filterInfoMap.put(key, saturnBundleFilterInfo);
	}
	
	/**
	 * 获取过滤器的实现类
	 * @param className
	 * @return
	 */
	public ISaturnFilter getSaturnFilter(String className){
		try {
			Class<?> c = LoaderUtils.loadClass(className);
			Object obj = c.newInstance();
			if (obj instanceof ISaturnFilter) {
				ISaturnFilter saturnFilter = (ISaturnFilter) obj;
				return saturnFilter;
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 获取过滤器信息的集合
	 * @param bundleName
	 * @param url
	 * @return
	 */
	public List<SaturnFilterInfo> getFilterInfo(String url){
		List<SaturnFilterInfo> filterInfos = new ArrayList<SaturnFilterInfo>();
		Set<String> bundleNames = filterInfoMap.keySet();
		for(String bundleName:bundleNames){
			SaturnBundleFilterInfo saturnBundleFilterInfo = filterInfoMap.get(bundleName);
			if(saturnBundleFilterInfo != null){
				Map<String,SaturnFilterInfo> saturnFilterInfos = saturnBundleFilterInfo.getFilterInfoMap();
				Set<String> filterSet = saturnFilterInfos.keySet();
				SaturnFilterInfo saturnFilterInfo;
				for(String str:filterSet){
					if(isFullMatching(url,str)){
						saturnFilterInfo = saturnFilterInfos.get(str);
						filterInfos.add(saturnFilterInfo);
					}
				}
			}
		}
		return filterInfos;
	}
	
	/**
	 * 判断访问路径是否匹配过滤条件
	 * 配置路径中"*"为通配符，匹配一级目录或文件，用在结尾处，表示匹配该目录下的所有文件；
	 * "**"为通配符，匹配多级目录，不可以应用在路径结尾
	 * @param url	访问路径	
	 * @param path  配置路径
	 * @return		匹配结果
	 */
	public boolean isFullMatching(String url, String path){
		/*if(path.equals("/*")||path.equals(url)){
		return true;
		}*/
		String [] urls = url.split("/");
		String [] paths = path.split("/");
		int urlLength = urls.length;
		int pathLength = paths.length;
		int urlNum = 0;
		for(int pathNum = 0;pathNum<pathLength;pathNum++){
			if(paths[pathNum].equals("**")){
				if(pathNum == pathLength-1){
					return false;
				}
				pathNum++;
				urlNum++;
				while(true){
					if(urlNum == urlLength-1){
						if(pathNum == pathLength-1 && isEndMatching(urls[urlNum],paths[pathNum])){
							return true;
						}else{
							return false;
						}				
					}
					if(isMatching(urls[urlNum],paths[pathNum])){
						urlNum++;
						break;
					}
					urlNum++;
				}
			}else if(pathNum == pathLength-1 && paths[pathNum].equals("*")){
				return true;
			}else{
				if(urlNum == urlLength-1){
					if(pathNum == pathLength-1 && isEndMatching(urls[urlNum],paths[pathNum])){
						return true;
					}else{
						return false;
					}				
				}else{
					if(!isMatching(urls[urlNum],paths[pathNum])){
						return false;
					}
				}
				urlNum++;
			}
		}
		return true;
	}
	
	private boolean isEndMatching(String url, String path){
		if(isMatching(url,path)){
			return true;
		}
		String [] urls = url.split("[.]");
		String [] paths = path.split("[.]");
		int ul = urls.length;
		int pl = paths.length;
		if(ul!=pl){
			return false;
		}
		for(int i =0;i<ul;i++){
			if(!isMatching(urls[i],paths[i])){
				return false;
			}
		}
		return true;
	}
	
	private boolean isMatching(String url, String path){
		return path.equals("*") || path.equals(url);
	}
	
}
